
import Foundation

public extension String {
    
    /// get substring by range. "hello"[0..<3] = "hel", "hello"[3..<"hello".count] = "lo"
    ///
    /// - Parameter range: range for target
    subscript(_ range: CountableRange<Int>) -> String {
        let idx1 = index(startIndex, offsetBy: range.lowerBound)
        let idx2 = index(startIndex, offsetBy: range.upperBound)
        return String(self[idx1..<idx2])
    }
    
    /// Trim white space and Newline character for string from leading and trailing
    public var trim : String { return self.trimmingCharacters(in: .whitespacesAndNewlines) }
    
    /// Trim all white space and Newline character for string
    public var trimAll: String {
        var str = self.trim
        str = str.replacingOccurrences(of: " ", with: "")
        str = str.replacingOccurrences(of: "\n", with: "")
        str = str.replacingOccurrences(of: "\r", with: "")
        str = str.replacingOccurrences(of: "\n\r", with: "")
        str = str.replacingOccurrences(of: "\r\n", with: "")
        return str
    }
    
    
    /// Regex match
    ///
    /// - parameter strRegex: the regex in string
    public func matches(regex: String) -> Bool {
        
        let regex = try! NSRegularExpression(pattern: regex, options: .dotMatchesLineSeparators)
        return regex.numberOfMatches(in: self, options: .reportCompletion, range: NSMakeRange(0, self.count-1)) > 0 ? true : false
        
    }
    
    /// Validates a string by regex
    ///
    /// - Parameter regex: regex for validation
    /// - Returns: Bool value for validation result
    public func isValid(for regex: String) -> Bool {
        let regexTest = NSPredicate(format: "SELF MATCHES %@", regex)
        return regexTest.evaluate(with: self)
    }
    
    /// Catch a string
    ///
    /// - parameter str: catch string start at
    /// - parameter include: whether to include the start string
    public func subFrom(str: String, include: Bool) -> String {
        
        if str == "" {
            return self
        }
        
        let range = self.range(of: str)!
        return include ? String(self[range.lowerBound...]) : String(self[range.upperBound...])
    }
    
    /// Catch a string
    ///
    /// - parameter str: catch string end at
    /// - parameter include: whether to include the end string
    public func subTo(str: String, include: Bool) -> String {
        
        if str == "" {
            return self
        }
        
        let range = self.range(of: str)!
        
        return include ? String(self[..<range.upperBound]) : String(self[..<range.lowerBound])
    }
    
    /// Catch sub string by range [1..2]
    ///
    /// - Parameter r: range
//    public subscript (r: Range<Int>) -> String {
//        get {
//            let startIndex = self.index(self.startIndex, offsetBy: r.lowerBound)
//            let endIndex = self.index(self.startIndex, offsetBy: r.upperBound)
//            let range = startIndex..<endIndex
//            return String(self[range])
//        }
//    }
    
    
    /// Patch 1 to 01
    ///
    /// - Parameter a: int value for patch
    /// - Returns: string of the patched value
    public static func patchInt(_ a: Int) -> String {
        var r = ""
        if a < 10, a >= 0 {
            r = "0\(a)"
        } else {
            r = "\(a)"
        }
        return r
    }
    
    
    /// Convert a json string to dictionary
    ///
    /// - Returns: converted dictionary
    public func convertToDictionary() -> [String: Any]? {
        
        if let data = self.data(using: .utf8) {
            do {
                return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
            } catch {
                print("convertToDictionary error: \(error.localizedDescription)")
            }
        }
        
        return nil
    }
}


// MARK: - random
extension  String {
    
    public static func random() -> String {
        var string = ""
        let stringLength = (arc4random() % 100) + 1000
        for i in 0..<stringLength {
            if (i+1) % 5 == 0 {
                string += " "
            }
            string += String(format: "%C", unichar(uint("a") + arc4random_uniform(25)))
        }
        return string
    }
}

